<?php

/**
 * @version  2.0
 * @author   guokunsheng
 * @date     2016-11-17
 */
namespace App\Tools;


use Illuminate\Routing\Controller;
use Cache;


class Jssdk
{
    private $appId;// 微信公众号appid
    private $appSecret;// 微信公众号appSecret

    public function __construct()
    {
        $this->appId = config('wechat.mp_appid');// 从数据库配置中获取
        $this->appSecret = config('wechat.mp_secret');// 从数据库配置中获取
    }

    public function getSignPackage($url = '')
    {
        // 获取js-sdk临时票据
        $jsapiTicket = $this->getJsApiTicket();

        if($url == '')
        {
            $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "https://";
            $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
        }

        $timestamp = time();
        $nonceStr = $this->createNonceStr();

        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
        $signature = sha1($string);

        $signPackage = array(
            "appId"     => $this->appId,
            "nonceStr"  => $nonceStr,
            "timestamp" => $timestamp,
            "url"       => $url,
            "signature" => $signature,
            "rawString" => $string
        );
        return $signPackage;
    }

    /**
     * 生成随机字符串
     * @param int $length
     * @return string
     */
    private function createNonceStr($length = 16)
    {
        $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     *  获取js-sdk临时票据
     * @return mixed
     */
    private function getJsApiTicket()
    {
        
        $data = Cache::get('js_api_ticket');

        if (!is_array($data)) $data = json_decode($data,true);

        if (empty($data) || !isset($data['expire_time']) || $data['expire_time'] < time())
        {
            $accessToken = $this->getAccessToken();
            // 如果是企业号用以下 URL 获取 ticket
//             $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
    
            $res = json_decode($this->httpGet($url),true);

            if($res['errcode'] == 0  && isset($res['ticket']))
            {
                $ticket = $res['ticket'];
                $data = [
                    'expire_time'=>time() + 7000,
                    'jsapi_ticket' => $res['ticket'],
                ];
                Cache::set('js_api_ticket',json_encode($data),7000);
            }
            elseif($res['errcode'] == 40001)
            {
                // access_token 失效 清空
                Cache::forget('js_access_token');

                $accessToken = $this->getAccessToken();
                $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";

                $res = json_decode($this->httpGet($url),true);

                if($res['errcode'] == 0  && isset($res['ticket']))
                {
                    $ticket = $res['ticket'];
                    $data = [
                        'expire_time'=>time() + 7000,
                        'jsapi_ticket' => $res['ticket'],
                    ];
                    Cache::set('js_api_ticket',json_encode($data),7000);
                }
                else
                {
                    $ticket = '';
                }
            }
            else
            {
                \Log::info('js_api_ticket_error:'.var_export($res,true));
                $ticket = '';
            }
        }
        else
        {
            $ticket = $data['jsapi_ticket'];
        }

        return $ticket;
    }

    private function getAccessToken()
    {
        $data = Cache::get('js_access_token');
         
        if (!is_array($data)) $data = json_decode($data,true);

        if (empty($data) || !isset($data['expire_time']) || $data['expire_time'] < time())
        {
            // 如果是企业号用以下URL获取access_token
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
            $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";

            $res = json_decode($this->httpGet($url),true);
            if(isset($res['access_token']))
            {
                $access_token = $res['access_token'];

                $data = [
                    'expire_time'=>time() + 7000,
                    'access_token' => $access_token,
                ];

                Cache::set('js_access_token',json_encode($data),7000);
            } else {
                \Log::info('js_access_token_error:'.var_export($res,true));
                $access_token = '';
            }
        } else {
         
            $access_token = $data['access_token'];
        }
        return $access_token;
    }
    // curl获取指定地址数据
    private function httpGet($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 500);
        // 为保证第三方服务器与微信服务器之间数据传输的安全性，所有微信接口采用https方式调用，必须使用下面2行代码打开ssl安全校验。
        // 如果在部署过程中代码在此处验证失败，请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 2);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($curl, CURLOPT_URL, $url);

        $res = curl_exec($curl);
        curl_close($curl);
        return $res;
    }
}